package com.cuts.videoedit.util

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.media.MediaMetadataRetriever
import android.net.Uri
import androidx.core.graphics.createBitmap
import java.io.ByteArrayOutputStream
import java.io.File

class VideoUtils {

    companion object {
        fun getVideoDuration(context: Context, videoPath: String?): Long? {
            val retriever = MediaMetadataRetriever()
            retriever.setDataSource(context, Uri.fromFile(File(videoPath)))
            val duration =
                retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong()
            retriever.release()
            return duration
        }

        /**
         * 计算获取缩放比例inSampleSize
         */
        private fun calculateInSampleSize(
            options: BitmapFactory.Options,
            reqWidth: Int,
            reqHeight: Int
        ): Int {
            val height = options.outHeight
            val width = options.outWidth
            var inSampleSize = 1
            if (height > reqHeight || width > reqWidth) {
                val heightRatio = Math.round(height.toFloat() / reqHeight.toFloat())
                val widthRatio = Math.round(width.toFloat() / reqWidth.toFloat())
                inSampleSize = if (heightRatio < widthRatio) heightRatio else widthRatio
            }
            val totalPixels = (width * height).toFloat()
            val totalReqPixelsCap = (reqWidth * reqHeight * 2).toFloat()
            while (totalPixels / (inSampleSize * inSampleSize) > totalReqPixelsCap) {
                inSampleSize++
            }
            return inSampleSize
        }
        /**
         * 第二种：按采样大小压缩
         *
         * @param src       源图片
         * @param maxWidth  最大宽度
         * @param maxHeight 最大高度
         * @param recycle   是否回收
         * @return 按采样率压缩后的图片
         */
        fun compressBySampleSize(
            src: Bitmap?,
            maxWidth: Int,
            maxHeight: Int,
            recycle: Boolean
        ): Bitmap? {
            if (src == null || src.width == 0 || src.height == 0) {
                return null
            }
            val options = BitmapFactory.Options()
            options.inJustDecodeBounds = true
            val baos = ByteArrayOutputStream()
            src.compress(Bitmap.CompressFormat.JPEG, 100, baos)
            val bytes = baos.toByteArray()
            BitmapFactory.decodeByteArray(bytes, 0, bytes.size, options)
            options.inSampleSize = VideoUtils.calculateInSampleSize(options, maxWidth, maxHeight)
            options.inJustDecodeBounds = false
            if (recycle && !src.isRecycled) {
                src.recycle()
            }
            val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size, options)
            return bitmap
        }
        fun YUVToNv21(y: ByteArray, u: ByteArray, v: ByteArray): ByteArray {
            //4、交叉存储VU数据
            val lengthY = y.size
            val lengthU = u.size
            val lengthV = v.size

            val newLength = lengthY + lengthU + lengthV
            val arrayNV21 = ByteArray(newLength)

            //先将所有的Y数据存储进去
            System.arraycopy(y, 0, arrayNV21, 0, lengthY)

            //然后交替存储VU数据(注意U，V数据的长度应该是相等的，记住顺序是VU VU)
            for (i in 0..<lengthV) {
                val index = lengthY + i * 2
                arrayNV21[index] = v[i]
            }

            for (i in 0..<lengthU) {
                val index = lengthY + i * 2 + 1
                arrayNV21[index] = u[i]
            }
            return arrayNV21
        }
        /**
         * 将nv21转bitmap
         * @param data
         * @param width
         * @param height
         * @param practicalWidth  实际宽度，ffmpeg 解码出来的宽度可能会因为16位对齐的问题多出来一些无用数据，绘制的时候这些数据不绘制
         * @return
         */
        fun rawByteArray2RGBABitmap2(
            data: ByteArray,
            width: Int,
            height: Int,
            practicalWidth: Int
        ): Bitmap {
            val frameSize = width * height
            val rgba = IntArray(frameSize)
            for (i in 0..<height) for (j in 0..<width) {
                var y = (0xff and (data[i * width + j].toInt()))
                val u =
                    (0xff and (data[frameSize + (i shr 1) * width + (j and 1.inv()) + 0].toInt()))
                val v =
                    (0xff and (data[frameSize + (i shr 1) * width + (j and 1.inv()) + 1].toInt()))
                y = if (y < 16) 16 else y
                var r = Math.round(1.164f * (y - 16) + 1.596f * (v - 128))
                var g = Math.round(1.164f * (y - 16) - 0.813f * (v - 128) - 0.391f * (u - 128))
                var b = Math.round(1.164f * (y - 16) + 2.018f * (u - 128))
                r = if (r < 0) 0 else (if (r > 255) 255 else r)
                g = if (g < 0) 0 else (if (g > 255) 255 else g)
                b = if (b < 0) 0 else (if (b > 255) 255 else b)
                rgba[i * width + j] = -0x1000000 + (b shl 16) + (g shl 8) + r
            }

            val bmp = createBitmap(width, height, Bitmap.Config.RGB_565)
            bmp.setPixels(rgba, 0, width, 0, 0, practicalWidth, height)
            return bmp
        }
    }
}